namespace Gsl.Eigensystems
{
    using System;
    using System.Runtime.InteropServices;

    public class RealSymmetric
    {
        [DllImport("libgsl")]
        private static extern IntPtr gsl_eigen_symmv_alloc(int n);
        
        [DllImport("libgsl")]
        private static extern void gsl_eigen_symmv_free(IntPtr workspace);
        
        int size;
        IntPtr workspace;
        
        public RealSymmetric(int size)
        {
            this.size = size;
            workspace = gsl_eigen_symmv_alloc(size);
        }
        
        ~RealSymmetric()
        {
            gsl_eigen_symmv_free(workspace);
        }
        
        // warning:  this function needs a function in libgslcblas, which
        // is not pulled in because of bad linking (I guess).
        // So if you need this function, do a
        // "LD_PRELOAD=/usr/lib/libgslcblas.so"
        // before running your program
        // or ... (new) ... just add the sqrt" function in gslcblas and run it somewhere
        [DllImport("libgsl")]
        private static extern int gsl_eigen_symmv(Matrix A, Vector eval, Matrix evec, IntPtr w);
        [DllImport("libgslcblas")]
        private static extern double sqrt(double x);
        
        public void Calculate(ref Matrix m, out Vector values, out Matrix vectors)
        {
            values = new Vector(size);
            vectors = new Matrix(size, size);
            sqrt(1.0);
            gsl_eigen_symmv(m, values, vectors, workspace);
        }                    
    }
}
